package com.kvw.filesystem.core.minio;

import com.kvw.filesystem.config.MinioStorageConfig;
import com.kvw.filesystem.core.S3Storage;
import com.kvw.filesystem.exception.FileSystemException;
import com.kvw.filesystem.model.FileObject;
import io.minio.*;
import io.minio.messages.Bucket;
import org.apache.commons.collections4.CollectionUtils;

import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created with IntelliJ IDEA.
 * Desc:
 *
 * @author: keen
 * Date: 2020-07-29
 * Time: 22:34
 */
public class MinioStorage extends S3Storage {
    private MinioClient minioClient;
    private MinioStorageConfig minioConfig;

    public MinioStorage() {
        this(MinioStorageConfig.getDefaultMinioConfig());
    }

    public MinioStorage(MinioStorageConfig minioConfig) {
        this.minioConfig = minioConfig;
        init();
    }

    private void init() {
        minioClient = MinioClient.builder()
                .endpoint(minioConfig.getHost(), minioConfig.getPort(), minioConfig.isSecure())
                .credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey()).build();
    }

    @Override
    public void makeBucket(String bucketName) throws FileSystemException {
        MakeBucketArgs args = MakeBucketArgs.builder().bucket(bucketName).build();
        try {
            minioClient.makeBucket(args);
        } catch (Exception e) {
            throw new FileSystemException(e.getMessage(), e);
        }
    }

    @Override
    public List<String> listBuckets() throws FileSystemException {
        try {
            List<Bucket> buckets = minioClient.listBuckets();
            if (CollectionUtils.isNotEmpty(buckets)) {
                return buckets.stream().map(Bucket::name).collect(Collectors.toList());
            }
            return Collections.emptyList();
        } catch (Exception e) {
            throw new FileSystemException(e.getMessage(), e);
        }
    }

    @Override
    public boolean bucketExists(String bucketName) throws FileSystemException {
        BucketExistsArgs args = BucketExistsArgs.builder().bucket(bucketName).build();
        try {
            return minioClient.bucketExists(args);
        } catch (Exception e) {
            throw new FileSystemException(e.getMessage(), e);
        }
    }

    @Override
    public void removeBucket(String bucketName) throws FileSystemException {
        RemoveBucketArgs args = RemoveBucketArgs.builder().bucket(bucketName).build();
        try {
            minioClient.removeBucket(args);
        } catch (Exception e) {
            throw new FileSystemException(e.getMessage(), e);
        }
    }

    /**
     * 上传文件
     *
     * @param fileObject
     * @return
     */
    @Override
    public String upload(FileObject fileObject) throws FileSystemException {
        String fileId = getUploadFileName(getFileId(), fileObject.getFileName());
        long fileSize = fileObject.getFileSize(), partSize = fileObject.getPartSize();
        try {
            if (fileSize == 0) {
                fileSize = fileObject.getDataSource().available();
            }
            if (partSize == 0) {
                partSize = -1L;
            }
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(fileObject.getBucket())
                    .stream(fileObject.getDataSource(), fileSize, partSize)
                    .object(fileId)
                    .userMetadata(fileObject.getMetadata())
                    .build();
            minioClient.putObject(putObjectArgs);
            return fileId;
        } catch (Exception e) {
            throw new FileSystemException(e.getMessage(), e);
        }
    }

    /**
     * 下载文件
     *
     * @param fileObject
     * @return
     */
    @Override
    public InputStream download(FileObject fileObject) throws FileSystemException {
        GetObjectArgs getObjectArgs = GetObjectArgs.builder()
                .bucket(fileObject.getBucket()).object(fileObject.getFileId()).build();
        try {
            return minioClient.getObject(getObjectArgs);
        } catch (Exception e) {
            throw new FileSystemException(e.getMessage(), e);
        }
    }

    /**
     * 删除文件
     *
     * @param fileObject
     * @return
     */
    @Override
    public boolean delete(FileObject fileObject) throws FileSystemException {
        RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder()
                .bucket(fileObject.getBucket())
                .object(fileObject.getFileId())
                .build();
        try {
            minioClient.removeObject(removeObjectArgs);
            return true;
        } catch (Exception e) {
            throw new FileSystemException(e.getMessage(), e);
        }
    }


}
